package com.example.demo.service;

import com.example.demo.bean.GoodsSeckill;
import com.example.demo.bean.Order;
import com.example.demo.bean.SeckillOrder;
import com.example.demo.bean.User;
import com.example.demo.dao.OrderDao;
import com.example.demo.exception.CodeMsg;
import com.example.demo.exception.GlobalException;
import com.example.demo.redis.RedisServer;
import com.example.demo.redisPrefix.GoodsPrefixAndExpireSecond;
import com.example.demo.redisPrefix.SeckillOrderPrefixAndExpireSecond;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

@Service
public class OrderService {

    @Autowired
    private OrderDao orderDao;

    @Autowired
    private RedisServer redisServer;




    public Order findOrderInfro(Long orderId){
        return orderDao.findOrderById(orderId);
    }


    //要同时在秒杀订单表和订单详情表中都新增一条数据，所以要保证两个数据同时操作,原子性操作
    @Transactional
    public Integer insertOrderInfro(User user, GoodsSeckill goods){
        Order orderInfo = new Order();
        orderInfo.setCreateDate(new Date());
        orderInfo.setDeliveryAddrId(0L);
        orderInfo.setGoodsCount(1);
        orderInfo.setGoodsId(goods.getId());
        orderInfo.setGoodsName(goods.getGoodsName());
        orderInfo.setGoodsPrice(goods.getGoodsPrice());
        orderInfo.setOrderChannel(1);
        orderInfo.setStatus(0);
        orderInfo.setUserId(user.getId());
        //写入订单详情表
        long orderId = orderDao.insert(orderInfo);

        System.out.println(orderId);
        SeckillOrder seckillOrder = new SeckillOrder();
        seckillOrder.setGoodsId(goods.getId());
        seckillOrder.setOrderId(orderId);
        seckillOrder.setUserId(user.getId());

        //写入秒杀订单表
        int flag = orderDao.insertSeckillOrder(seckillOrder);
        //数据操操作完成


        //为了减少与数据库的查询验证是否秒杀成功，直接将存入订单的信息存入redis
        try {
            redisServer.set(SeckillOrderPrefixAndExpireSecond.goodsSeckilled,""+user.getId()+goods.getId(),orderId);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            throw new GlobalException(CodeMsg.SERVER_ERROR);
        }
        return flag;
    }



    public Integer findSeckillResultByRedis(User user,Long goodsId){
        Long userId = user.getId();

       Integer flag=0;

        /*
        * 因为是异步下单，所以并不知道具体的结果，大概有三种结果
        * 1.程序还没进行数据库操作，还在运行中，有可能此时刚抢到令牌或者刚进入队列
        * 2.程序不能执行数据库秒杀商品库存减一操作，有可能是自己抢到了版本号，但进行数据库减一的时候发现商品突然描述变为0了
        * 3.就是成功操作完成数据库，秒杀商品已经存入秒杀商品详情表和秒杀商品订单表
        * */
        try {
            flag = redisServer.get(SeckillOrderPrefixAndExpireSecond.goodsSeckilled, "" + userId + goodsId,Integer.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        if (flag>0){

            //第三种情况说明秒杀成功
            return 1;
        }else {
            //查询redis种是否有第二种情况的记录
            Boolean flagExist=false;
            try {
                flagExist= redisServer.get(GoodsPrefixAndExpireSecond.goodsOver, "" + goodsId,Boolean.class);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            if (flagExist==true){
                //代表卖完了
                return -1;
            }else {
                //说明程序还在运行中
                return 0;
            }
        }
    }


}
